/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2023. All rights reserved.
 * Description: UDK byte order for x86 architecture header file
 * Author: -
 * Create: 2021.4.20
 */

#ifndef UDK_BYTEORDER_X86_H
#define UDK_BYTEORDER_X86_H

#include <stdint.h>

static inline uint16_t udk_arch_bswap16(uint16_t _x)
{
    uint16_t x = _x;
    asm volatile("xchgb %b[x1],%h[x2]" : [ x1 ] "=Q"(x) : [ x2 ] "0"(x));
    return x;
}

static inline uint32_t udk_arch_bswap32(uint32_t _x)
{
    uint32_t x = _x;
    asm volatile("bswap %[x]" : [ x ] "+r"(x));
    return x;
}

static inline uint64_t udk_arch_bswap64(uint64_t _x)
{
    uint64_t x = _x;
    asm volatile("bswap %[x]" : [ x ] "+r"(x));
    return x;
}

#define UDK_CONSTANT_BSWAP16(v) \
    ((uint16_t)((((uint16_t)(v) & UINT16_C(0x00ff)) << 8) | (((uint16_t)(v) & UINT16_C(0xff00)) >> 8)))

#define UDK_CONSTANT_BSWAP32(v)                                                                              \
    ((uint32_t)((((uint32_t)(v) & UINT32_C(0x000000ff)) << 24) | (((uint32_t)(v) & UINT32_C(0x0000ff00)) << 8) | \
    (((uint32_t)(v) & UINT32_C(0x00ff0000)) >> 8) | (((uint32_t)(v) & UINT32_C(0xff000000)) >> 24)))

#define UDK_CONSTANT_BSWAP64(v)                                                                                       \
    ((uint64_t)((((uint64_t)(v) & UINT64_C(0x00000000000000ff)) << 56) |                                              \
    (((uint64_t)(v) & UINT64_C(0x000000000000ff00)) << 40) | (((uint64_t)(v) & UINT64_C(0x0000000000ff0000)) << 24) | \
    (((uint64_t)(v) & UINT64_C(0x00000000ff000000)) << 8) | (((uint64_t)(v) & UINT64_C(0x000000ff00000000)) >> 8) |   \
    (((uint64_t)(v) & UINT64_C(0x0000ff0000000000)) >> 24) | (((uint64_t)(v) & UINT64_C(0x00ff000000000000)) >> 40) | \
    (((uint64_t)(v) & UINT64_C(0xff00000000000000)) >> 56)))

/*
 * Byte swap for an constant 16-bit value.
 */
static inline uint16_t udk_constant_bswap16(uint16_t x)
{
    return UDK_CONSTANT_BSWAP16(x);
}

/*
 * Byte swap for an constant 32-bit value.
 */
static inline uint32_t udk_constant_bswap32(uint32_t x)
{
    return UDK_CONSTANT_BSWAP32(x);
}

/*
 * Byte swap for an constant 64-bit value.
 */
static inline uint64_t udk_constant_bswap64(uint64_t x)
{
    return UDK_CONSTANT_BSWAP64(x);
}

#define udk_bswap16(x) ((uint16_t)(__builtin_constant_p(x) ? udk_constant_bswap16(x) : udk_arch_bswap16(x)))
#define udk_bswap32(x) ((uint32_t)(__builtin_constant_p(x) ? udk_constant_bswap32(x) : udk_arch_bswap32(x)))
#define udk_bswap64(x) ((uint64_t)(__builtin_constant_p(x) ? udk_constant_bswap64(x) : udk_arch_bswap64(x)))

#endif /* UDK_BYTEORDER_X86_H */